home *** CD-ROM | disk | FTP | other *** search
/ Revista do CD-ROM 97 / CD-ROM 97 / CD-ROM 97.iso / internet / ghostzilla / ghsetup.exe / chrome / comm.jar / content / editor / EdLinkProps.js < prev    next >
Encoding:
JavaScript  |  2002-04-09  |  11.3 KB  |  367 lines

  1. /* 
  2.  * The contents of this file are subject to the Netscape Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/NPL/
  6.  *  
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  *  
  12.  * The Original Code is Mozilla Communicator client code, released
  13.  * March 31, 1998.
  14.  * 
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation. Portions created by Netscape are
  17.  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
  18.  * Rights Reserved.
  19.  * 
  20.  * Contributor(s): 
  21.  */
  22.  
  23. var anchorElement = null;
  24. var imageElement = null;
  25. var insertNew = false;
  26. var replaceExistingLink = false;
  27. var insertLinkAtCaret;
  28. var needLinkText = false;
  29. var href;
  30. var newLinkText;
  31. var gHNodeArray = [];
  32. var gHaveNamedAnchors = false;
  33. var gHaveHeadings = false;
  34. var gCanChangeHeadingSelected = true;
  35. var gCanChangeAnchorSelected = true;
  36. var gHaveDocumentUrl = false;
  37.  
  38. // NOTE: Use "href" instead of "a" to distinguish from Named Anchor
  39. // The returned node is has an "a" tagName
  40. var tagName = "href";
  41.  
  42. // dialog initialization code
  43. function Startup()
  44. {
  45.   if (!InitEditorShell())
  46.     return;
  47.  
  48.   // Message was wrapped in a <label> or <div>, so actual text is a child text node
  49.   gDialog.linkTextCaption     = document.getElementById("linkTextCaption");
  50.   gDialog.linkTextMessage     = document.getElementById("linkTextMessage");
  51.   gDialog.linkTextInput       = document.getElementById("linkTextInput");
  52.   gDialog.hrefInput           = document.getElementById("hrefInput");
  53.   gDialog.makeRelativeLink    = document.getElementById("MakeRelativeLink");
  54.   gDialog.AdvancedEditSection = document.getElementById("AdvancedEdit");
  55.  
  56.   var selection = editorShell.editorSelection;
  57.   if (selection)
  58.     dump("There is a selection: collapsed = "+selection.isCollapsed+"\n");
  59.   else
  60.     dump("Failed to get selection\n");
  61.  
  62.   // See if we have a single selected image
  63.   imageElement = editorShell.GetSelectedElement("img");
  64.  
  65.   if (imageElement)
  66.   {
  67.     // Get the parent link if it exists -- more efficient than GetSelectedElement()
  68.     anchorElement = editorShell.GetElementOrParentByTagName("href", imageElement);
  69.     if (anchorElement)
  70.     {
  71.       if (anchorElement.childNodes.length > 1)
  72.       {
  73.         // If there are other children, then we want to break
  74.         //  this image away by inserting a new link around it,
  75.         //  so make a new node and copy existing attributes
  76.         anchorElement = anchorElement.cloneNode(false);
  77.         //insertNew = true;
  78.         replaceExistingLink = true;
  79.       }
  80.     }
  81.   }
  82.   else
  83.   {
  84.     // Get an anchor element if caret or
  85.     //   entire selection is within the link.
  86.     anchorElement = editorShell.GetSelectedElement(tagName);
  87.  
  88.     if (anchorElement)
  89.     {
  90.       // Select the entire link
  91.       editorShell.SelectElement(anchorElement);
  92.       selection = editorShell.editorSelection;
  93.     }
  94.     else
  95.     {
  96.       // If selection starts in a link, but extends beyond it,
  97.       //   the user probably wants to extend existing link to new selection,
  98.       //   so check if either end of selection is within a link
  99.       // POTENTIAL PROBLEM: This prevents user from selecting text in an existing
  100.       //   link and making 2 links. 
  101.       // Note that this isn't a problem with images, handled above
  102.  
  103.       anchorElement = editorShell.GetElementOrParentByTagName("href", selection.anchorNode);
  104.       if (!anchorElement)
  105.         anchorElement = editorShell.GetElementOrParentByTagName("href", selection.focusNode);
  106.  
  107.       if (anchorElement)
  108.       {
  109.         // But clone it for reinserting/merging around existing
  110.         //   link that only partially overlaps the selection
  111.         anchorElement = anchorElement.cloneNode(false);
  112.         //insertNew = true;
  113.         replaceExistingLink = true;
  114.       }
  115.     }
  116.   }
  117.  
  118.   if(!anchorElement)
  119.   {
  120.     // No existing link -- create a new one
  121.     anchorElement = editorShell.CreateElementWithDefaults(tagName);
  122.     insertNew = true;
  123.     // Hide message about removing existing link
  124.     //document.getElementById("RemoveLinkMsg").setAttribute("hidden","true");
  125.   }
  126.   if(!anchorElement)
  127.   {
  128.     dump("Failed to get selected element or create a new one!\n");
  129.     window.close();
  130.     return;
  131.   } 
  132.  
  133.   // We insert at caret only when nothing is selected
  134.   insertLinkAtCaret = selection.isCollapsed;
  135.   
  136.   var selectedText;
  137.   if (insertLinkAtCaret)
  138.   {
  139.     // Groupbox caption:
  140.     gDialog.linkTextCaption.setAttribute("label", GetString("LinkText"));
  141.  
  142.     // Message above input field:
  143.     gDialog.linkTextMessage.setAttribute("value", GetString("EnterLinkText"));
  144.   }
  145.   else
  146.   {
  147.     if (!imageElement)
  148.     {
  149.       // We get here if selection is exactly around a link node
  150.       // Check if selection has some text - use that first
  151.       selectedText = GetSelectionAsText();
  152.       if (!selectedText) 
  153.       {
  154.         // No text, look for first image in the selection
  155.         var children = anchorElement.childNodes;
  156.         if (children)
  157.         {
  158.           for(var i=0; i < children.length; i++) 
  159.           {
  160.             var nodeName = children.item(i).nodeName.toLowerCase();
  161.             if (nodeName == "img")
  162.             {
  163.               imageElement = children.item(i);
  164.               break;
  165.             }
  166.           }
  167.         }
  168.       }
  169.     }
  170.     // Set "caption" for link source and the source text or image URL
  171.     if (imageElement)
  172.     {
  173.       gDialog.linkTextCaption.setAttribute("label", GetString("LinkImage"));
  174.       // Link source string is the source URL of image
  175.       // TODO: THIS DOESN'T HANDLE MULTIPLE SELECTED IMAGES!
  176.       gDialog.linkTextMessage.setAttribute("value", imageElement.src);
  177.     } else {
  178.       gDialog.linkTextCaption.setAttribute("label", GetString("LinkText"));
  179.       if (selectedText) 
  180.       {
  181.         // Use just the first 60 characters and add "..."
  182.         gDialog.linkTextMessage.setAttribute("value", TruncateStringAtWordEnd(ReplaceWhitespace(selectedText, " "), 60, true));
  183.       } else {
  184.         gDialog.linkTextMessage.setAttribute("value", GetString("MixedSelection"));
  185.       }
  186.     }
  187.   }
  188.  
  189.   // Make a copy to use for AdvancedEdit and onSaveDefault
  190.   globalElement = anchorElement.cloneNode(false);
  191.  
  192.   // Get the list of existing named anchors and headings
  193.   FillLinkMenulist(gDialog.hrefInput, gHNodeArray);
  194.  
  195.   // We only need to test for this once per dialog load
  196.   gHaveDocumentUrl = GetDocumentBaseUrl();
  197.  
  198.   // Set data for the dialog controls
  199.   InitDialog();
  200.   
  201.   // Search for a URI pattern in the selected text
  202.   //  as candidate href
  203.   selectedText = TrimString(selectedText); 
  204.   if (!gDialog.hrefInput.value && TextIsURI(selectedText))
  205.       gDialog.hrefInput.value = selectedText;
  206.  
  207.   // Set initial focus
  208.   if (insertLinkAtCaret) {
  209.     // We will be using the HREF inputbox, so text message
  210.     SetTextboxFocus(gDialog.linkTextInput);
  211.   } else {
  212.     SetTextboxFocus(gDialog.hrefInput);
  213.  
  214.     // We will not insert a new link at caret, so remove link text input field
  215.     gDialog.linkTextInput.setAttribute("hidden", "true");
  216.     gDialog.linkTextInput = null;
  217.   }
  218.     
  219.   // This sets enable state on OK button
  220.   doEnabling();
  221.  
  222.   SetWindowLocation();
  223. }
  224.  
  225. // Set dialog widgets with attribute data
  226. // We get them from globalElement copy so this can be used
  227. //   by AdvancedEdit(), which is shared by all property dialogs
  228. function InitDialog()
  229. {
  230.   // Must use getAttribute, not "globalElement.href", 
  231.   //  or foreign chars aren't coverted correctly!
  232.   gDialog.hrefInput.value = globalElement.getAttribute("href");
  233.  
  234.   // Set "Relativize" checkbox according to current URL state
  235.   SetRelativeCheckbox(gDialog.makeRelativeLink);
  236. }
  237.  
  238. function doEnabling()
  239. {
  240.   // We disable Ok button when there's no href text only if inserting a new link
  241.   var enable = insertNew ? (TrimString(gDialog.hrefInput.value).length > 0) : true;
  242.   
  243.   // anon. content, so can't use SetElementEnabledById here
  244.   var dialogNode = document.getElementById("linkDlg");
  245.   dialogNode.getButton("accept").disabled = !enable;
  246.  
  247.   SetElementEnabledById( "AdvancedEditButton1", enable);
  248. }
  249.  
  250. function ChangeLinkLocation()
  251. {
  252.   SetRelativeCheckbox();
  253.  
  254.   // Set OK button enable state
  255.   doEnabling();
  256. }
  257.  
  258. // Get and validate data from widgets.
  259. // Set attributes on globalElement so they can be accessed by AdvancedEdit()
  260. function ValidateData()
  261. {
  262.   href = TrimString(gDialog.hrefInput.value);
  263.   if (href)
  264.   {
  265.     // Set the HREF directly on the editor document's anchor node
  266.     //  or on the newly-created node if insertNew is true
  267.     globalElement.setAttribute("href",href);
  268.   }
  269.   else if (insertNew)
  270.   {
  271.     // We must have a URL to insert a new link
  272.     //NOTE: We accept an empty HREF on existing link to indicate removing the link
  273.     ShowInputErrorMessage(GetString("EmptyHREFError"));
  274.     return false;
  275.   }
  276.   if (gDialog.linkTextInput)
  277.   {
  278.     // The text we will insert isn't really an attribute,
  279.     //  but it makes sense to validate it
  280.     newLinkText = TrimString(gDialog.linkTextInput.value);
  281.     if (!newLinkText)
  282.     {
  283.       if (href)
  284.         newLinkText = href
  285.       else
  286.       {
  287.         ShowInputErrorMessage(GetString("EmptyLinkTextError"));
  288.         SetTextboxFocus(gDialog.linkTextInput);
  289.         return false;
  290.       }
  291.     }
  292.   }
  293.   return true;
  294. }
  295.  
  296. function doHelpButton()
  297. {
  298.   openHelp("link_properties");
  299.   return true;
  300. }
  301.  
  302. function onAccept()
  303. {
  304.   if (ValidateData())
  305.   {
  306.     if (href.length > 0)
  307.     {
  308.       // Copy attributes to element we are changing or inserting
  309.       editorShell.CloneAttributes(anchorElement, globalElement);
  310.  
  311.       // Coalesce into one undo transaction
  312.       editorShell.BeginBatchChanges();
  313.  
  314.       // Get text to use for a new link
  315.       if (insertLinkAtCaret)
  316.       {
  317.         // Append the link text as the last child node 
  318.         //   of the anchor node
  319.         var textNode = editorShell.editorDocument.createTextNode(newLinkText);
  320.         if (textNode)
  321.           anchorElement.appendChild(textNode);
  322.         try {
  323.           editorShell.InsertElementAtSelection(anchorElement, false);
  324.         } catch (e) {
  325.           dump("Exception occured in InsertElementAtSelection\n");
  326.           return true;
  327.         }
  328.       } else if (insertNew || replaceExistingLink)
  329.       {
  330.         //  Link source was supplied by the selection,
  331.         //  so insert a link node as parent of this
  332.         //  (may be text, image, or other inline content)
  333.         try {
  334.           editorShell.InsertLinkAroundSelection(anchorElement);
  335.         } catch (e) {
  336.           dump("Exception occured in InsertElementAtSelection\n");
  337.           return true;
  338.         }
  339.       }
  340.       // Check if the link was to a heading 
  341.       if (href[0] == "#")
  342.       {
  343.         var index = gDialog.hrefInput.selectedIndex;
  344.         if (index in gHNodeArray && gHNodeArray[index])
  345.         {
  346.           var anchorNode = editorShell.editorDocument.createElement("a");
  347.           if (anchorNode)
  348.           {
  349.             anchorNode.name = href.substr(1);
  350.             // Remember to use editorShell method so it is undoable!
  351.             editorShell.InsertElement(anchorNode, gHNodeArray[index], 0, false);
  352.           }
  353.         }
  354.       }
  355.       editorShell.EndBatchChanges();
  356.     } 
  357.     else if (!insertNew)
  358.     {
  359.       // We already had a link, but empty HREF means remove it
  360.       editorShell.RemoveTextProperty("a", "");
  361.     }
  362.     SaveWindowLocation();
  363.     return true;
  364.   }
  365.   return false;
  366. }
  367.